/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package xenon3d.scene;

import javax.media.opengl.GL2;
import xenon3d.vector.Color4f;

/**
 * The TextureAttributes object defines attributes that apply to texture mapping.
 * 
 * @author Volker Everts
 * @version 0.1 - 18.11.2011: Created
 */
public class TextureAttributes extends Attributes {
    
    // <editor-fold defaultstate="collapsed" desc=" Static Attributes ">
    
    /** The default TextureAttributes. */
    static final TextureAttributes DEFAULT = new TextureAttributes();
    
    /** The last active texture attribute object. */
    private static TextureAttributes last = DEFAULT;
    
    /** Helper array to convert colors to float[]. */
    private static float[] fv = new float[4];
    
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc=" Public Enumerations ">
    
    /**
     * An enumeration of texture border modes.
     */
    public static enum BorderMode {
        
        /**
         * Causes texture coordinate to be clamped to the range [0,1]. This is
         * useful for preventing wrapping artifacts when mapping a single image
         * onto an object.
         */
        Clamp (GL2.GL_CLAMP),
        
        /**
         * Causes the integer part of the texture coordinate to be ignored. Only
         * the fractional part is used, thereby creating a repeating pattern.
         */
        Repeat (GL2.GL_REPEAT);
        
        /** The OpenGL border mode value. */
        int value;
        
        /**
         * Creates a new BorderMode.
         * @param value the OpenGL border mode value
         */
        BorderMode(int value) {
            this.value = value;
        }
        
    } // end enum BorderMode
    
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc=" Private Fields ">
    
    /** The texture border color. */
    private Color4f borderColor = Color4f.SOLID_BLACK;
    
    /** The horizontal texture border mode. */
    private BorderMode borderModeH = BorderMode.Repeat;
    
    /** The vertical texture border mode. */
    private BorderMode borderModeV = BorderMode.Repeat;
        
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc=" Initialization ">
    
    /**
     * Creates a new TextureAttributes object with default settings. The default
     * settings are:<p>
     * <ul>
     * <li>BorderColor: SOLID_BLACK</li>
     * </ul>
     */
    public TextureAttributes() {}
    
    /**
     * Creates a new TextureAttributes object using the specified border color
     * and border mode. The border mode is used for horizontal coordinates as
     * well as for vertical,
     * @param color the border color
     * @param mode the horizontal and vertical border mode 
     */
    public TextureAttributes(Color4f color, BorderMode mode) {
        if (color == null || mode == null) throw new IllegalArgumentException();
        borderColor = color;
        borderModeH = mode;
        borderModeV = mode;
    }
    
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc=" Public Properties ">
    
    /**
     * Sets the texture border color.
     * @param color the new texture border color
     */
    public final void setBorderColor(Color4f color) {
        checkCapability(Capability.AllowTextureAttributesWrite);
        if (color == null) color = Color4f.SOLID_BLACK;
        borderColor = color;
    } 
    
    /**
     * Returns the texture border color.
     * @return the current texture border color
     */
    public final Color4f getBorderColor() {
        if (borderColor == Color4f.SOLID_BLACK) return null;
        return borderColor;
    }
    
    /**
     * Sets the horizontal texture border mode.
     * @param mode the new horizontal texture border mode
     */
    public final void setBorderModeH(BorderMode mode) {
        checkCapability(Capability.AllowTextureAttributesWrite);
        if (mode == null) mode = BorderMode.Repeat;
        borderModeH = mode;
    }
    
    /**
     * Returns the horizontal texture border mode.
     * @return the current horizontal texture border mode
     */
    public final BorderMode getBorderModeH() {
        return borderModeH;
    }
    
    /**
     * Sets the vertical texture border mode.
     * @param mode the new vertical texture border mode
     */
    public final void setBorderModeV(BorderMode mode) {
        checkCapability(Capability.AllowTextureAttributesWrite);
        if (mode == null) mode = BorderMode.Repeat;
        borderModeV = mode;
    }
    
    /**
     * Returns the vertical texture border mode.
     * @return the current vertical texture border mode
     */
    public final BorderMode getBorderModeV() {
        return borderModeV;
    }
    
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc=" Package Private Methods (OpenGL) ">
    
    @Override
    void apply(GL2 gl) {
        if (this == last) return;
        if (borderColor != last.borderColor) {
            borderColor.get(fv);
            gl.glTexParameterfv(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_BORDER_COLOR, fv, 0);
        }
        if (borderModeH != last.borderModeH) {
            gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, borderModeH.value);
        }
        if (borderModeV != last.borderModeV) {
            gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, borderModeH.value);
        }
        last = this;
    }
    
    // </editor-fold>
    
} // end class TextureAttributes